﻿#include "qterminaldisplay.h"
#include <QFontMetrics>
#include <QApplication>
#include <QColor>
#include <QKeyEvent>
#include <QPainter>
#include <QPalette>
#include <QDebug>
#include <qmath.h>
#include <QClipboard>
#undef print
#define print qDebug()
qTerminalDisplay::qTerminalDisplay(QWidget *parent):QWidget(parent)
{
    init();
}

qTerminalDisplay::~qTerminalDisplay()
{
   if(screen)
        delete screen;
}

void qTerminalDisplay::init()
{
    screen = new qTerminalScreen();
    setFocusPolicy( Qt::WheelFocus );

    // enable input method support
    setAttribute(Qt::WA_InputMethodEnabled, true);

    // this is an important optimization, it tells Qt
    // that TerminalDisplay will handle repainting its entire area.
    setAttribute(Qt::WA_OpaquePaintEvent, true);

    connect(&timerPaint,&QTimer::timeout,this,&qTerminalDisplay::timerPaintOut);
    connect(&timer2Paint,&QTimer::timeout,this,&qTerminalDisplay::timerPaintOut);
    this->setFocus();

    timerResize.setSingleShot(true);
    timerResize.setInterval(2000);//启动后自动更新界面大小
    
    connect(&timerResize,&QTimer::timeout,this,&qTerminalDisplay::resizeSlotsTimer);

    connect(screen,&qTerminalScreen::updateSignal,this,&qTerminalDisplay::updateTimerSlots);
    connect(screen,&qTerminalScreen::setScrollValue,this,[=](int min,int max,int page,int value)
    {
       // print<<"scroll value"<<min<<max<<page<<value;
        emit setScrollValue(min,max,page,value);
    });
    setMinimumWidth(screen->getFontWidth()*120);
    setMinimumHeight(screen->getFontHeight()*30);

    InitContextMenu();
}

int qTerminalDisplay::praseCsi(QString seq,qTerminalFont &terminalFont)
{
    bool handled = false;
    char ch=0;
    int index=0;
    int number=0;
    QByteArray data = seq.toLocal8Bit();
    char kind=data.at(data.count()-1);
    // print<<__FUNCTION__<<seq;

    if(seq.contains('?'))
    {
        if(seq == "?1l")//Normal Cursor Keys (DECCKM), VT100.
        {
            this->keyPadMode = false;
        }
        else if(seq == "?1h")// Application Cursor Keys (DECCKM), VT100
        {
            this->keyPadMode = true;
        }
        else if(seq == "?12l")//Stop blinking cursor (AT&T 610).
        {
        }
        else if(seq == "?25l")//Hide cursor (DECTCEM), VT220.
        {
            this->cursorHideFlag = true;
        }
        else if(seq == "?25h")//Show cursor (DECTCEM), VT220
        {
            this->cursorHideFlag = false;
        }
        else if(seq == "?7h")//Wraparound
        {

        }
        else if(seq == "?7l")// reset Wraparound
        {

        }
        else if(seq == "?1047l")//UseAltScreen
        {

        }
        else if(seq == "?1048l")//SaveCursor
        {

        }
        else if(seq == "?1049h")//UseAltScreenAndSaveCursor
        {
            screen->saveCursor();    
        }
        else if(seq == "?1049l")//reset UseAltScreenAndSaveCursor
        {
            screen->restoreCursor();
            screen->setRow(screen->getRowMax());
        }
        else if(seq == "?2004l")//Reset bracketed paste mode, xterm.
        {
            
        }
        else if(seq == "?2004h")//Set bracketed paste mode, xterm.
        {

        }
        else if(seq == "?12h")// Start blinking cursor (AT&T 610)
        {

        }
        else if(seq == "?1047h")//UseAltScreen
        {

        }
        else if(seq == "?1048h")//SaveCursor
        {

        }
        
        return true;
    }
    else
    {
        switch (kind)
        {
        case 'n':
            if(seq=="6n")
            {
                char tmp[20];
                sprintf(tmp,"\033[%d;%dR",screen->getScreenCursorY(),screen->getScreenCursorX());
                sendData(tmp);
            }
            else if(seq=="5n")
            {
                sendData("\033[0n");
            }

            break;
        case 'h':
            handled=true;
            break;
            // CSI Pm l  Reset Mode (RM).
            // Ps = 2  ⇒  Keyboard Action Mode (KAM).
            // Ps = 4  ⇒  Replace Mode (IRM).
            // Ps = 1 2  ⇒  Send/receive (SRM).
            // Ps = 2 0  ⇒  Normal Linefeed (LNM).
        case 'l':
            handled=true;
            break;

        case 'r':
        {
            QStringList hlist;
            index=0;
            number=0;
            hlist = seq.split(';');
            if(hlist.count()>1)
            {
                for(int i=0;i<hlist.count();i++)
                {
                    QByteArray arrary = hlist.at(i).toLocal8Bit();
                    foreach(auto ch,arrary)
                    {
                        if(ch>='0'&&ch<='9')
                        {
                            number = number*10+ch-'0';
                            index++;
                        }
                    }

                    number=0;
                    index=0;
                }
                screen->setCol(0);
                screen->setRow(screen->getBottom()+1);
            }
        }
            break;

        case '@':
            handled=true;
            break;

        case 'A':
        {
            number=0;
            for(int i=0;i<data.count();i++)
            {
                ch = data.at(i);
                if(ch>='0'&&ch<='9')
                {
                    number = number*10+ch-'0';
                }
                else
                {
                    break;
                }
            }
            if(number==0)
                number=1;
            screen->setRow(screen->getRow()-number);
        }
            handled=true;
            break;

        case 'B':
            handled=true;
            break;
        case 'C':
        case 'a':
            screen->setCol(screen->getCol()+1);
            updateTimerSlots();
            handled=true;
            break;
        case 'D':
            handled=true;
            break;

        case 'E':
            handled=true;
            break;

        case 'F':
            handled=true;
            break;

        case 'G':
        case '`':
        {
            number=0;
            QByteArray arrary = seq.toLocal8Bit();
            foreach(auto ch,arrary)
            {
                if(ch>='0'&&ch<='9')
                {
                    number = number*10+ch-'0';
                }
                else
                {
                    break;
                }
            }
            if(number==0)
                number = 1;
            if(number!=0)
            {
                screen->setCol(number-1);
            }
        }
            handled=true;
            break;

        case 'H':
        case 'f':
        {
            QStringList hlist;
            index=0;
            int _row=0,_col=0;

            number=0;
            hlist = seq.split(';');
            if(hlist.count()>1)
            {
                for(int i=0;i<hlist.count();i++)
                {
                    QByteArray arrary = hlist.at(i).toLocal8Bit();
                    foreach(auto ch,arrary)
                    {
                        if(ch>='0'&&ch<='9')
                        {
                            number = number*10+ch-'0';
                            index++;
                        }
                    }
                    if(_row==0 && i==0 )
                        _row=number;
                    if(_col==0 && i==1)
                        _col=number;
                    number=0;
                    index=0;
                }
                
            }
            if(_col>0)
                _col = _col - 1;
            //print<<__func__<<__LINE__<<screen->getSaveCursorY()<<_row;
            screen->setRow(screen->getSaveCursorY()+_row);
            screen->setCol(_col);
            screen->replace('\0',screen->getRow(),screen->getCol(),terminalFont);
        }
            handled=true;
            break;

        case 'I':
            handled=true;
            break;

        case 'J'://从光标往后全部清除
        {
            if(seq=="0J"||seq=="J")
            {
                for (quint32 i=screen->getRow();i<screen->getRowMax();i++) {
                    int r = i % screen->getScreenBufSize();
                    screen->clearToEnd(r,0);
                }
            }
            else if(seq=="1J")//从从屏幕开头到光标全部清除
            {
                quint32 i = 0;
                if(screen->getSaveCursorY()==0)
                i=screen->getTop();
                else
                    i = screen->getSaveCursorY();
                for (;i<(screen->getRow()-1) % screen->getScreenBufSize();i++) {
                    screen->clearToEnd(i,0);
                }
                for( i=0;i<screen->getCol();i++)
                {
                    screen->replace(' ',(screen->getRow()) % screen->getScreenBufSize(),i,terminalFont);
                }
            }
            else if(seq=="2J")//清屏
            {
                quint32 i = 0;
                if(screen->getSaveCursorY()==0)
                i=screen->getTop();
                else
                    i = screen->getSaveCursorY();
                screen->clearScreen(i);
            }
            else if(seq=="3J")//Erase Saved Lines, xterm.
            {
            }
            //screen->setCol(0);
            handled=true;
        }
            break;

        case 'K':
        {
            if(seq=="0K"||seq=="K")//从光标擦到行尾
            {
                screen->clearToEnd(screen->getRow(),screen->getCol());
            }
            else if(seq=="1K")//从光标擦到行首
            {
                //emit lineClearColStart(screen->getRow(),screen->getCol());
                //screen->setCol(0);
                for(quint32 i=0;i<screen->getCol();i++)
                {
                    screen->replace(' ',screen->getRow(),i,terminalFont);
                }
            }
            else if(seq=="2K")//整行擦除
            {
                //emit lineClearColEnd(screen->getRow(),0);
                //screen->setCol(0);
                screen->clearToEnd(screen->getRow(),0);
            }
        }
            handled=true;
            break;

        case 'L':
            handled=true;
            break;

        case 'M':
            handled=true;
            break;

        case 'P'://删除字符
        {
            index=0;
            number=0;
            QByteArray arrary = seq.toLocal8Bit();
            foreach(auto ch,arrary)
            {
                if(ch>='0'&&ch<='9')
                {
                    number = number*10+ch-'0';
                    index++;
                }
            }
            screen->clearToEnd(screen->getRow(),screen->getCol());//xterm 256 del键适配
        }
            handled=true;
            break;

        case 'S':
            handled=true;
            break;

        case 'T':
            handled=true;
            break;

        case 'X'://CSI Ps X  Erase Ps Character(s) (default = 1) (ECH).
        // {
        //     number=0;
        //     QByteArray arrary = seq.toLocal8Bit();
        //     foreach(auto ch,arrary)
        //     {
        //         if(ch>='0'&&ch<='9')
        //         {
        //             number = number*10+ch-'0';
        //         }
        //         else
        //         {
        //             break;
        //         }
        //     }
        //     if(number==0)
        //         number = 1;
        //     for(quint32 i=0;i<screen->getCol()&&i<number;i++)
        //     {
        //         screen->replace(' ',screen->getRow(),i,terminalFont);
        //     }
        // }
            handled=true;
            break;

        case 'Z':
            handled=true;
            break;

        case 'd':
        {
            number=0;
            QByteArray arrary = seq.toLocal8Bit();
            foreach(auto ch,arrary)
            {
                if(ch>='0'&&ch<='9')
                {
                    number = number*10+ch-'0';
                }
                else
                {
                    break;
                }
            }
            if(number==0)
                number = 1;
            if(number!=0)
            {
                quint32 i = 0;
                if(screen->getSaveCursorY()==0)
                    i=screen->getTop();
                else
                    i = screen->getSaveCursorY();
                screen->setRow(i-1);
            }
        }
            handled=true;
            break;

        case 'e':
            handled=true;
            break;

        case 'm':
        {
            if(seq=="30m")//表示让后面字符输出用前景黑色输出
            {

                terminalFont.background = QColor(Qt::white);
                terminalFont.foreground = QColor(Qt::black);
            }
            else if(seq=="m" || seq=="0m")//表示取消前面的设置。
            {
                terminalFont.background = QColor(Qt::black);
                terminalFont.foreground = QColor(Qt::white);
            }
            else if(seq=="1m")//粗体
            {
                terminalFont._b_bold = true;
            }
            else if(seq=="2m")//虚化（暗淡）
            {
                terminalFont.foreground.setAlpha(150);
            }
            else if(seq=="3m")//斜体
            {
                terminalFont._b_italic = true;
            }
            else if(seq=="4m")//下划线
            {
                terminalFont._b_underLine = true;
            }
            else if(seq=="5m")//闪烁
            {

            }
            else if(seq=="7m")// 反显
            {
                terminalFont.background = QColor(Qt::white);
                terminalFont.foreground = QColor(Qt::black);
            }
            else if(seq=="8m")//消隐
            {
                //terminalFont.foreground.setAlpha(0);
            }
            else if(seq=="9m")//删除线
            {
                terminalFont._b_strikeout = true;
            }
            else if(seq=="01;30m")//前景色 黑色
            {
                terminalFont.foreground = QColor(Qt::black);
            }
            else if(seq=="01;31m")//前景色 红色
            {
                terminalFont.foreground = QColor(Qt::red);
            }
            else if(seq=="01;32m")//
            {
                terminalFont.foreground = QColor(Qt::green);
            }
            else if(seq=="01;33m")//
            {
                terminalFont.foreground = QColor(Qt::yellow);
            }
            else if(seq=="01;34m")//删除线3b78ff 729aff blue
            {
                terminalFont.foreground = QColor(0x72,0x80,0xff);
            }
            else if(seq=="01;35m")//purple
            {
                terminalFont.foreground = QColor(Qt::magenta);
            }
            else if(seq=="01;36m")//cyan
            {
                terminalFont.foreground = QColor(Qt::cyan);
            }
            else if(seq=="01;37m")//白色
            {
                terminalFont.foreground = QColor(Qt::white);
            }
            else if(seq=="01;39m")//删除线
            {
                terminalFont.foreground = QColor(Qt::white);
            }
            else if(seq=="01;40m")//删除线
            {
                terminalFont.background = QColor(Qt::black);
            }
            else if(seq=="01;41m")//删除线
            {
                terminalFont.background = QColor(Qt::red);
            }
            else if(seq=="01;42m")//删除线
            {
                terminalFont.background = QColor(Qt::green);
            }
            else if(seq=="01;43m")//删除线
            {
                terminalFont.background = QColor(Qt::yellow);
            }
            else if(seq=="01;44m")//删除线
            {
                terminalFont.background = QColor(0x72,0x80,0xff);
            }
            else if(seq=="01;45m")//删除线
            {
                terminalFont.background = QColor(Qt::magenta);
            }
            else if(seq=="01;46m")//删除线
            {
                terminalFont.background = QColor(Qt::cyan);
            }
            else if(seq=="01;47m")//删除线
            {
                terminalFont.background = QColor(Qt::white);
            }
            else if(seq=="01;49m")//删除线
            {
                terminalFont.background = QColor(Qt::black);
            }
            handled=true;
        }
            break;
        case 's':
            handled=true;
            break;

        case 'u':
            handled=true;
            break;
        case '!':
            handled=true;
            break;
        default:
            handled = false;
            break;
        }

    }

    return handled;
}

void qTerminalDisplay::praseChar(QByteArray data)
{
    uchar ch=0;
   QString text = QString::fromUtf8(data);
   print<<__FUNCTION__<<"recv:"<<text<<this->type;

    if(data.isEmpty())
        return;
    QString seqence="";
    qTerminalFont terminalFont;
    int count = data.size();
    for(int i=0;i<count;i++)
    {
        ch = data.at(i);
        switch(this->type)
        {
        case praseType::text:
            if(ch==0x1b)
            {
                this->type=praseType::esc;
                break;
            }
            else if(ch=='\n')
            {
                screen->setCol(0);
                screen->setRow(screen->getRow()+1);
                screen->replace('\x0',screen->getRow(),screen->getCol(),terminalFont);
                //resizeSlots();
            }
            else if(ch=='\r')
            {
                //print<<__func__<<__LINE__<<screen->getRow()<<screen->getCol()<<screen->getColMax();
                if(screen->getCol()!=0)
                {
                    if((screen->getCol())>screen->getColMax()-screen->getLeftMargin())
                    {
                       // print<<__func__<<__LINE__<<screen->getRow()<<screen->getCol()<<screen->getColMax();
                        screen->setCol(screen->getCol()-1);
                        screen->clearToEnd(screen->getRow(),screen->getCol());
                        screen->setCol(0);
                        screen->setRow(screen->getRow()+1);
                        screen->replace('\x0',screen->getRow(),screen->getCol(),terminalFont);
                        //resizeSlots();
                        print<<__func__<<__LINE__<<screen->getRow()<<screen->getCol()<<screen->getColMax();
                        updateTimerSlots();
                        break;
                    }
                }
                //print<<__func__<<__LINE__<<screen->getRow()<<screen->getCol()<<screen->getColMax();
                screen->setCol(0);
                updateTimerSlots();
            }
            else if(ch=='\b')
            {
                screen->setCol(screen->getCol()-1);
                updateTimerSlots();
            }
            else if(ch=='\x7')
            {
                //响铃
                QApplication::beep();
            }
            else
            {
                if(ch<32)
                {

                }
                else
                {
                    screen->replace(ch,screen->getRow(),screen->getCol(),terminalFont);
                    screen->setCol(screen->getCol()+1);
                }
            }
            break;
        case praseType::esc:
            if (ch == '[')
                this->type = praseType::csi;
            else if (ch == ']')
                this->type = praseType::osc;
            else if (ch == '>')//bracket
            {
                this->type = praseType::text;

                break;
            }
            else if (ch == '(')
            {
                this->type = praseType::bracket;
                // page_row = screen->getRow();
                break;
            }
            else if (ch == '=')//Application Keypad (DECKPAM).
            {
                // this->keyPadMode = true;
                // page_row = screen->getRow();
                // screen->setCol(0);
                this->type = praseType::text;
                break;
            }
            else if (ch >= '0')
            {
                screen->setCol(screen->getCol()+1);

                this->type = praseType::text;
            }
            else
            {
                this->type = praseType::esc2;
            }
            break;
        case praseType::esc2:
            this->type = praseType::text;
            break;
        case praseType::csi:
            seqence+=ch;
            if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))
            {
                praseCsi(seqence,terminalFont);
                seqence="";
                this->type = praseType::text;
            }
            break;
        case praseType::osc:
            seqence+=ch;
            if(ch<32)
            {
                seqence="";
                this->type = praseType::text;
            }
            break;
        case praseType::bracket:
            if(ch=='c')
            {


            }
            else
            {

            }
            this->type = praseType::text;
            break;
        default:
            break;
        }

    }
    //emit lineChangedContentSignal(screen->getRow(),screen->getCol());//发送当前的字符信息

    //print<<__FUNCTION__<<__LINE__<<"recv:"<<QDateTime::currentDateTime();
}

void qTerminalDisplay::recvData(QByteArray data)
{
    praseChar(data);
}

void qTerminalDisplay::sendData(QString data)
{
    print<<"sendData"<<data;
    emit sendDataStringSlgnal(data);
    emit sendDataByteArrarySlgnal(data.toUtf8());
}

void qTerminalDisplay::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::RightButton||event->button() == Qt::MidButton)
        return;
    screen->scrollChangedValue=0;
    selectX=event->x();
    selectY=event->y();
    selectRow = (qCeil( selectY/screen->getFontHeight())+screen->getTop())%screen->getScreenBufSize();
    // QVector<qTerminalCharSet> run = this->terminalLine->getRow(selectRow);
    selectCol = qCeil(selectX/screen->getFontWidth());
    print<<__FUNCTION__<<selectRow<<selectCol<<event->x()<<event->y();;
}

void qTerminalDisplay::mouseReleaseEvent(QMouseEvent *event)
{
    if(event->button() == Qt::RightButton||event->button() == Qt::MidButton)
        return;
    
    screen->scrollChangedValue=0;
    print<<__FUNCTION__<<event->x()<<event->y()<<event->button()<<Qt::RightButton;
    if(selectX==event->x()&&selectY==event->y())
    {
        this->selected=true;
        selectEndRow = 0;
        selectEndCol = 0;
        selectEndCol = 0;
        selectCol = 0;
        screen->scrollChangedValue=0;
        // print<<"aa"<<__FUNCTION__<<event->x()<<event->y();
        this->update(contentsRect());
    }
}

void qTerminalDisplay::mouseMoveEvent(QMouseEvent *event)
{
    if(event->buttons() == Qt::RightButton||event->buttons() == Qt::MidButton)
        return;
    selectEndX=event->x();
    selectEndY=event->y();
    
    int h = screen->getFontHeight();
    this->update(contentsRect());

    selectEndRow = (qCeil( selectEndY/h)+screen->getTop())%screen->getScreenBufSize();
    selectEndCol = qCeil(selectEndX/screen->getFontWidth());
    print<<__FUNCTION__<<selectEndRow<<selectEndCol<<screen->getFontWidth();
    this->selected=false;
}

void qTerminalDisplay::wheelEvent(QWheelEvent *event)
{
    if (event->orientation() != Qt::Vertical)
        return;
    int tmp =event->angleDelta().y()/8/5>0?1:-1;
    
    if(screen->getWheelShowFlag()==false)
        return;
    
    screen->scrollHandle(tmp);
    emit setScrollBarPos(-tmp);
}

void qTerminalDisplay::keyPressEvent(QKeyEvent *event)
{
    int c = event->key();
    QString key=event->text();
    switch(c)
    {
    case Qt::Key_Enter:
        break;
    case Qt:: Key_Return:
        //screen->setCol(0);
        key="\r";
        //resizeSlots();
        break;
    case Qt::Key_Left:
        if(this->keyPadMode )
        {
            key="\x1bOD";
        }
        else
        {
            key="\x1b[D";
        }
        break;
    case Qt::Key_Down:
        if(this->keyPadMode )
        {
            key="\x1bOB";
        }
        else
        {
            key="\x1b[B";
        }
        break;
    case Qt::Key_Up:
        if(this->keyPadMode )
        {
            key="\x1bOA";
        }
        else
        {
            key="\x1b[A";
        }
        break;
    case Qt::Key_Right:
        if(this->keyPadMode )
        {
            key="\x1bOC";
        }
        else
        {
            key="\x1b[C";
        }
        break;
    case Qt::Key_Home:
        if(this->keyPadMode )
        {
            key="\x1bOH";
        }
        else
        {
            key="\u001b[H";
        }
        break;
    case Qt::Key_End:
        if(this->keyPadMode )
        {
            key="\x1bOF";
        }
        else
        {
            key="\u001b[F";
        }
        break;
    case Qt::Key_PageUp:
        key="\u001b[5~";
        break;
    case Qt::Key_PageDown:
        key="\u001b[6~";
        break;

    case Qt::Key_Insert:
        key="\x1b[2~";
        break;
    case Qt::Key_Delete://
        key="\x1b[3~";
        break;
    case Qt::Key_Shift:
        key="";
        break;
    default:
        break;
    }
    this->selected=true;//取消选中
    selectEndRow = 0;
    selectEndCol = 0;
    selectEndCol = 0;
    selectCol = 0;
    screen->setWheelFlag(false);
    // if((event->modifiers() == Qt::ControlModifier) && (event->key() == Qt::Key_C))
    // {
    //     emit contorlCStopSignal();
    // }
    if((event->modifiers() == Qt::ShiftModifier) && (event->key() == Qt::Key_Insert))
    {
        //粘贴
        pasteContent();
        return;
    }
    if((event->modifiers() == Qt::ShiftModifier) && (event->key() == Qt::Key_Delete))
    {
        //复制
        copyContentToClipBoard();
        return;
    }
    sendData(key);
}

int qTerminalDisplay::updateTimerSlots()
{
    // timer2Paint.setSingleShot(true);
    // timer2Paint.start(40);
    if (!timerPaint.isActive())
    {
        timerPaint.setSingleShot(true);
        timerPaint.start(40);
    }
    return 0;
}

void qTerminalDisplay::timerPaintOut()
{
    timerPaint.stop();
    timer2Paint.stop();
    QRect tL  = contentsRect();
    update(tL);
}
QByteArray arrary;
QRect rectangle;
QRectF boundingRect;
QString s="";
void qTerminalDisplay::paintEvent(QPaintEvent *event)
{
    int row_mmm=0,row_overCount=0;
    int x=0;
    QPainter painter(this);
    // mutex.lock();
    quint32 i=0,pos=1;
    int j=0;
    if(screen->getRowMax()==0)
        return;
    if(screen->getTop()>screen->getScreenBufSize())
        return;
    painter.drawPixmap(0, 0, _backgroundImage);
    QColor background = QColor(Qt::black);
    painter.fillRect(contentsRect(), background);
    
    painter.save();
    if(!this->cursorHideFlag)
    {
        rectangle = QRect(screen->cursorPosition().x(),
                        screen->cursorPosition().y(),
                        screen->getFontWidth(),
                        screen->getFontHeight());
        painter.setBrush(QColor(231, 151, 41,250));
        painter.setPen(QColor(231, 151, 41,250));
        painter.drawRect(rectangle);

        painter.setBrush(Qt::NoBrush);
    }
    foreach (const QRect &rect, (event->region() & contentsRect()).rects())
    {
        // print<<"paintEvent2"<<"x:"<<rect.x()<<"y:"<<rect.y()<<"width:"<<rect.width()<<"height"<<
        //        rect.height()<<MAX(rect.y()/screen->getFontHeight(),row_mmm)<<screen->rowMaxCount<<i<<row_mmm;
        //continue;
        row_mmm=0;
        i=screen->getTop();
        if(i>screen->getScreenBufSize())
            break;
        while(1)
        {
            _lineChars& lines = screen->getLineContent()[i];
            
            if(row_mmm*(int)screen->getFontHeight()>=rect.height())
                break;
            if(lines.size()>0)
                x=0;
            for(j=0;j<lines.size();j++)
            {
                
                if((lines.at(j).ch&0x80)!=0 )
                {

                }
                else
                {
                    if((quint32)j>screen->getColMax()*pos)//一行放不下，需要换行绘制
                    {
                        pos++;
                        row_mmm++;
                        row_overCount++;
                        //print<<__func__<<__LINE__<<screen->getRow()<<screen->getCol()<<screen->getColMax()<<j;
                        x=screen->getLeftMargin()*screen->getFontWidth();
                    }
                    s = lines.at(j).ch;
                    //unistr[m++] = lines.at(j).ch;
                    //print<<__FUNCTION__<<selectEndRow<<selectEndCol<<selectEndY<<selectY;


                    rectangle = QRect(x, row_mmm*screen->getFontHeight(), screen->getFontWidth(), screen->getFontHeight());
                    //print<<lines.at(j).terminalFont.background<<lines.at(j).terminalFont.foreground<<QColor(Qt::white)<<QColor(Qt::cyan);
                    painter.setBrush(lines.at(j).terminalFont.background);
                    painter.setPen(lines.at(j).terminalFont.background);

                    paintSelectContent(&painter,row_mmm,j,rectangle);
                    
                    painter.drawRect(rectangle);
                    painter.setBrush(Qt::NoBrush);
                    
                    painter.setFont(screen->font);
                    painter.setPen(lines.at(j).terminalFont.foreground);
                    
                    painter.drawText(rectangle,Qt::AlignTop|Qt::AlignLeft,s,&boundingRect);
                    x+=screen->getFontWidth();
                }
            }
            pos=1;
            if(i==screen->getBottom()||i==screen->getRowMax()%screen->getScreenBufSize())
                break;
            i++;
            i = i%screen->getScreenBufSize();
            row_mmm++;
        }

    }

    painter.restore();
    ///绘制输入法内容
    int len = _inputMethodData.preeditString.length();
    if ( len==0 )
        return;

    const QColor foreground = QColor(Qt::white);;

    rectangle =preeditRect();

    painter.setBrush(QColor(Qt::black));
    painter.setPen(QColor(Qt::black));
    painter.drawRect(rectangle);

    painter.setBrush(Qt::NoBrush);

    //print<<"x:"<<rectangle.x()<<"y:"<<rectangle.y()<<"width:"<<rectangle.width()<<"height"<<rectangle.height()<<row_mmm;
    painter.setFont(screen->getFont());
    painter.setPen(foreground);

    painter.drawText(_inputMethodData.previousPreeditRect,Qt::AlignTop|Qt::AlignLeft,_inputMethodData.preeditString,&boundingRect);

    rectangle = QRect(screen->cursorPosition().x()+len*screen->getFontWidth(), screen->cursorPosition().y(), screen->getFontWidth(), screen->getFontHeight());
    painter.setBrush(QColor(231, 151, 41,250));
    painter.setPen(QColor(231, 151, 41,250));
    painter.drawRect(rectangle);

    painter.setBrush(Qt::NoBrush);
}

void qTerminalDisplay::resizeSlotsTimer()
{
    int row_overCount=0;
    quint32 i=screen->getTop();
    _lineChars * ll = screen->getLineContent();
    if(i>screen->getScreenBufSize())
        return;
    while(1)
    {
        if((quint32)ll[i].size()>screen->getColMax())
        {
            row_overCount += (int)((float)ll[i].size()/(float)screen->getColMax());
        }
        if(i==screen->getBottom())
            break;
        i++;
        i = i%screen->getScreenBufSize();
    }
    int _rows = contentsRect().height()/screen->getFontHeight()-1-row_overCount;
    int _col = contentsRect().width()/screen->getFontWidth()-1;

    screen->setBottom(screen->getTop()+_rows);
    screen->setScreenRange(_rows);
    screen->setColMax(_col-screen->getLeftMargin());
    print<<__func__<<__LINE__<<screen->getRow()<<screen->getCol()<<screen->getColMax()<<screen->getLeftMargin()<<_rows<<_col;
    //emit setScrollPageSignal(_rows);
    emit resizeSignal(_rows,_col-screen->getLeftMargin());
}

void qTerminalDisplay::resizeEvent(QResizeEvent *event)
{
    resizeSlots();
}

void qTerminalDisplay::resizeSlots()
{
    resizeSlotsTimer();
    timerResize.start();
}

QRect qTerminalDisplay::preeditRect() const
{
    int len  = _inputMethodData.preeditString.length();
    if (len == 0 )
        return QRect();

    return QRect(screen->cursorPosition().x(),
                 screen->cursorPosition().y(),
                 screen->getFontWidth()*(len+1),
                 screen->getFontHeight());
}

void qTerminalDisplay::inputMethodEvent(QInputMethodEvent *e)
{
    screen->setWheelFlag(false);
    sendData(e->commitString());//输入法输入完成
    QString preeditString = e->preeditString();//输入法输入中
    _inputMethodData.preeditString = e->preeditString();
    _inputMethodData.previousPreeditRect = preeditRect();
    update(contentsRect()|_inputMethodData.previousPreeditRect);
    print<<__func__<<preeditString<<e->commitString()<<e->replacementStart()<<e->replacementLength();
    e->accept();
}

QVariant qTerminalDisplay::inputMethodQuery(Qt::InputMethodQuery query) const
{
    if(!screen)
        return QVariant();
    if(screen->getRowMax()==0)
        return QVariant();
    switch ( query )
    {
    case Qt::ImMicroFocus:
        print<<__func__<<"ImMicroFocus";
        return QRect(0,0,screen->getColMax()*screen->getFontWidth(),(screen->getRow()%screen->getRowMax()+1)*screen->getFontHeight());//高度是输入法显示位置相对于控件的上边
        break;
    case Qt::ImFont:
        print<<__func__<<"ImFont";
        return this->screen->getFont();
        break;
    case Qt::ImCursorPosition:
        print<<__func__<<"ImCursorPosition";
        break;
    case Qt::ImSurroundingText:
        print<<__func__<<"ImSurroundingText";
        break;
    case Qt::ImCurrentSelection:
        print<<__func__<<"ImCurrentSelection";
        break;
    default:
        break;
    }
    return QVariant();
}

bool qTerminalDisplay::event(QEvent *event)
{
    if (event->type() == QEvent::KeyPress) {

        QKeyEvent *ke = static_cast<QKeyEvent *>(event);

        if (ke->key() == Qt::Key_Tab) {
            sendData("\t");
            return true;
        }
    }
    return QWidget::event(event);
}

void qTerminalDisplay::sliderMovedScrollBarPosition(int value)
{
    print<<__func__<<  value;
    int tmp = screen->getScrollCurrent() - value;
    if(screen->getWheelShowFlag()==false)
        return;
    
    screen->scrollHandle(tmp);
}

void qTerminalDisplay::valueChangedSlots(int value)
{
    print<<__func__<<  value;
    if(value<0)
        value=0;
    screen->setScrollCurrent(value);
}

void qTerminalDisplay::setFocusSlots()
{
    this->setFocus();
}

char qTerminalDisplay::copySelectContent(int current_row,int current_col)
{
    int _selectEndRow=0,_selectRow=0;
    _selectEndRow=(selectEndRow)%screen->getScreenBufSize();
    _selectRow=(selectRow)%screen->getScreenBufSize();

    if(current_col>=screen->getLeftMargin()&&this->selected==false&&
            current_row>=MIN(_selectEndRow,_selectRow)&&current_row<=MAX(_selectEndRow,_selectRow))//行内容一定在被绘制行范围里面
    {
        if(MAX(_selectEndRow,_selectRow)-MIN(_selectEndRow,_selectRow)==0)//选择当前行
        {
            if(current_col>=MIN(selectCol,selectEndCol)&&current_col<=MAX(selectCol,selectEndCol))
            {
                goto end;
            }
        }
        else if(MAX(_selectEndRow,_selectRow)-MIN(_selectEndRow,_selectRow)>=1)//跨行复制
        {
            if(_selectEndRow>_selectRow)//从selectRow行开始往下选择
            {
                if(current_row==_selectRow)//先画最开始的行
                {
                    if(current_col>=selectCol)
                    {
                        goto end;
                    }
                }
                else if(current_row>_selectRow&&current_row<_selectEndRow)//在范围里的直接画
                {
                    goto end;
                }
                else if(current_row==_selectEndRow)//再画最后一行
                {
                    if(current_col<=selectEndCol)
                    {
                        goto end;
                    }
                }
            }
            else  if(_selectRow>_selectEndRow)//从selectRow行开始往下选择
            {
                if(current_row==_selectEndRow)//先画最开始的行
                {
                    if(current_col>=selectEndCol)
                    {
                        goto end;
                    }
                }
                else if(current_row>_selectEndRow&&current_row<_selectRow)//在范围里的直接画
                {
                    goto end;
                }
                else if(current_row==_selectRow)//再画最后一行
                {
                    if(current_col<=selectCol)
                    {
                        goto end;
                    }
                }
            }

        }
    }
    return '\0';
end:
    return screen->getLineContent()[current_row%screen->getScreenBufSize()].at(current_col).ch;
}

void qTerminalDisplay::paintSelectContent(QPainter *painter,int current_row,int current_col,QRect rectangle)
{
    int _selectEndRow=0,_selectRow=0;
    int _selectEndCol=0,_selectCol=0;
    _selectEndCol=selectEndCol;
    _selectCol=selectCol;
    
    _selectEndRow=(selectEndRow)%screen->getScreenBufSize();
    _selectRow=(selectRow)%screen->getScreenBufSize();
    
    current_row+=screen->getTop();
    current_row=(current_row)%screen->getScreenBufSize();
//print<<"aa;"<<__FUNCTION__<<selectEndRow<<selectEndCol<<selectRow<<selectCol<<screen->getTop()<<_selectRow<<_selectCol<<current_row<<current_col;
    if(current_col>=screen->getLeftMargin()&&this->selected==false&&
            current_row>=MIN(_selectEndRow,_selectRow)&&current_row<=MAX(_selectEndRow,_selectRow))//行内容一定在被绘制行范围里面
    {
        if(MAX(_selectEndRow,_selectRow)-MIN(_selectEndRow,_selectRow)==0)//选择当前行
        {
            if(current_col>=MIN(_selectCol,selectEndCol)&&current_col<=MAX(_selectCol,selectEndCol))
            {
                goto end;
            }
        }
        else if(MAX(_selectEndRow,_selectRow)-MIN(_selectEndRow,_selectRow)>=1)//跨行复制
        {
            if(_selectEndRow>_selectRow)//从selectRow行开始往下选择
            {
                if(current_row==_selectRow)//先画最开始的行
                {
                    if(current_col>=_selectCol)
                    {
                        goto end;
                    }
                }
                else if(current_row>_selectRow&&current_row<_selectEndRow)//在范围里的直接画
                {
                    goto end;
                }
                else if(current_row==_selectEndRow)//再画最后一行
                {
                    if(current_col<=selectEndCol)
                    {
                        goto end;
                    }
                }
            }
            else  if(_selectRow>_selectEndRow)//从selectRow行开始往下选择
            {
                if(current_row==_selectEndRow)//先画最开始的行
                {
                    if(current_col>=selectEndCol)
                    {
                        goto end;
                    }
                }
                else if(current_row>_selectEndRow&&current_row<_selectRow)//在范围里的直接画
                {
                    goto end;
                }
                else if(current_row==_selectRow)//再画最后一行
                {
                    if(current_col<=_selectCol)
                    {
                        goto end;
                    }
                }
            }

        }
        //
    }
    return;
end:
    painter->setBrush(QColor(231, 151, 41,250));
    painter->setPen(QColor(231, 151, 41,250));
    painter->drawRect(rectangle);
    return;
}

void qTerminalDisplay::customContextMenuRequestedSlots(const QPoint &pos)
{
    m_ContextMenu->popup(mapToGlobal(pos));
}

void qTerminalDisplay::copyContentToClipBoard()
{
    quint32 i=0,j=0;
    char ch;
    QString content="";

    i = (MIN(selectEndRow,selectRow))%screen->getScreenBufSize();
    while(1)
    {
        _lineChars& lines = screen->getLineContent()[i];
        for(j=0;j<(quint32)lines.size();j++)
        {
            ch =  copySelectContent(i,j);
            if(ch!='\0')
            {
                content +=ch;
            }

        }
        if(i>=((quint32)MAX(selectEndRow,selectRow))%screen->getScreenBufSize() || i==screen->getRowMax()%screen->getScreenBufSize())
        {
            break;
        }
        if(content!=""&&(selectEndRow!=selectRow))
            content+="\r\n";
        
        i++;
        i = i%screen->getScreenBufSize();
    }
    if(content!="")
    {
        QClipboard *clipBoard = QApplication::clipboard();
        clipBoard->setText(content);
    }
}

void qTerminalDisplay::pasteContent()
{
    QClipboard *clipBoard = QApplication::clipboard();
    QString content = clipBoard->text();
    if(content!="")
    {
        sendData(content);
    }
}

void qTerminalDisplay::InitContextMenu()
{
    //    print<<__FUNCTION__;
    this->setContextMenuPolicy(Qt::CustomContextMenu);

    connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(customContextMenuRequestedSlots(const QPoint&)));
    m_ContextMenu = new QMenu(this);
    QAction* m_actCopy = new QAction(QIcon(":/ico/copy.png"),tr("Copy"),m_ContextMenu);//复制
    QAction* m_actPaste= new QAction(QIcon(":/ico/paste.png"),tr("Paste"),m_ContextMenu);//粘贴
    QAction* m_actFind= new QAction(QIcon(":/ico/find.png"),tr("Find"),m_ContextMenu);//查找
    QAction* m_actSelectAll= new QAction(QIcon(":/ico/selectAll"),tr("Select All"),m_ContextMenu);//全选
    m_ContextMenu->addAction(m_actCopy);
    m_ContextMenu->addAction(m_actPaste);
    m_ContextMenu->addAction(m_actFind);
    m_ContextMenu->addAction(m_actSelectAll);

    QMenu* m_MenuTransmitBinFile= new QMenu(tr("Transmit bin file"),m_ContextMenu);//传输二进制文件
    m_MenuTransmitBinFile->setIcon(QIcon(":/ico/transimit.png"));
    QAction* m_actXmodem= new QAction(QIcon(":/ico/x.png"),"xmodem",m_MenuTransmitBinFile);//x modem协议
    QAction* m_actYmodem= new QAction(QIcon(":/ico/y.png"),"ymodem",m_MenuTransmitBinFile);//y modem协议
    QAction* m_actZmodem= new QAction(QIcon(":/ico/z.png"),"zmodem",m_MenuTransmitBinFile);//z modem协议
    QAction* m_actTransmitBinFileCancle= new QAction(QIcon(":/ico/cancle.png"),tr("Cancle transmit"),this);//取消传输二进制文件
    m_MenuTransmitBinFile->addAction(m_actXmodem);
    m_MenuTransmitBinFile->addAction(m_actYmodem);
    m_MenuTransmitBinFile->addAction(m_actZmodem);
    m_MenuTransmitBinFile->addAction(m_actTransmitBinFileCancle);

    m_ContextMenu->addMenu(m_MenuTransmitBinFile);

    connect(m_actCopy, &QAction::triggered, this, [=](bool checked){
        Q_UNUSED(checked);
        copyContentToClipBoard();
    });
    connect(m_actPaste, &QAction::triggered, this, [=](bool checked){
        Q_UNUSED(checked);
        pasteContent();
    });
    connect(m_actFind, &QAction::triggered, this, [=](bool checked){
        Q_UNUSED(checked);
    });
    connect(m_actSelectAll, &QAction::triggered, this, [=](bool checked){
        Q_UNUSED(checked);
        quint32 rowmax = screen->getRowMax();
        quint32 bufmax = screen->getScreenBufSize();


        selectRow=0;
        
        selectEndRow = rowmax;
        selectEndCol=screen->getColMax();
        selectCol=0;
        print<<selectRow<<selectCol<<selectEndRow<<selectEndCol<<selectEndRow%screen->getScreenBufSize()<<selectRow%screen->getScreenBufSize();
        this->selected=false;//可以选中
        this->update(contentsRect());
    });
    connect(m_actXmodem, &QAction::triggered, this, [=](bool checked){
        Q_UNUSED(checked);
    });
    connect(m_actYmodem, &QAction::triggered, this, [=](bool checked){
        Q_UNUSED(checked);
    });
    connect(m_actZmodem, &QAction::triggered, this, [=](bool checked){
        Q_UNUSED(checked);
    });
    connect(m_actTransmitBinFileCancle, &QAction::triggered, this, [=](bool checked){
        Q_UNUSED(checked);
    });
}
